﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Xml;
using System.IO;
using System.Xml.Linq;

namespace RssBar
{
    /// <summary>
    /// Klasa przechowująca ustawienia aplikacji
    /// </summary>
    public static class Configuration
    {
        /// <summary>
        /// konstuktor statyczny
        /// </summary>
        static Configuration()
        {
            //stwórz listę
            if (Configuration.HistoryList == null)
                Configuration.HistoryList = new List<RssMessage>();
        }

        /// <summary>
        /// Wczytuje konfigurację
        /// </summary>
        public static void Load()
        {
            //jeżeli plik nie istnieje stwórz nowy
            if (!File.Exists(CONFIG_FILE))
                Save();

            //wyczyść listę jeżeli jest stworzona
            if (Configuration.HistoryList != null)
                Configuration.HistoryList.Clear();

            try
            {
                XDocument config = XDocument.Load(CONFIG_FILE);

                //application
                Configuration.TopMost = bool.Parse(config.Root.Element("application").Attribute("topmost").Value);
                Configuration.ShowInTaskbar = bool.Parse(config.Root.Element("application").Attribute("showInTaskbar").Value);
                Configuration.ShowInTray = bool.Parse(config.Root.Element("application").Attribute("showInTray").Value);

                //channel
                Configuration.ChannelAddress = config.Root.Element("channel").Attribute("address").Value;

                //proxy
                WebProxy proxy = new WebProxy();
                
                string proxyAddr = config.Root.Element("proxy").Attribute("address").Value;
                int proxyPort = int.Parse(config.Root.Element("proxy").Attribute("port").Value);
                if (!string.IsNullOrEmpty(proxyAddr) && proxyPort > -1)
                    proxy.Address = new Uri(string.Format("{0}:{1}", proxyAddr, proxyPort));

                proxy.Credentials = new NetworkCredential(config.Root.Element("proxy").Attribute("username").Value,
                    config.Root.Element("proxy").Attribute("password").Value);

                proxy.UseDefaultCredentials = bool.Parse(config.Root.Element("proxy").Attribute("useDefaultCredentials").Value);

                Configuration.Proxy = proxy;

                //history list
                foreach (var entry in config.Root.Element("history").Elements())
                {
                    if (entry != null)
                    {
                        RssMessage rssMessage = new RssMessage();
                        rssMessage.Details.Title = entry.Attribute("title").Value;
                        rssMessage.Details.Description = entry.Attribute("description").Value;
                        rssMessage.Details.Link = new Uri(entry.Attribute("link").Value);
                        rssMessage.Details.PubDate = DateTime.Parse(entry.Attribute("pubDate").Value);
                        rssMessage.IsVisited = bool.Parse(entry.Attribute("isVisited").Value);

                        Configuration.HistoryList.Add(rssMessage);
                    }
                }
            }
            catch (Exception e)
            {
                IApplication.Logger.Write(IApplication.LoggerEventType.Error, e.Message, "[Configuration.Load] Błąd podczas odczytywania pliku XML!");
            }
        }

        /// <summary>
        /// Zapisuje konfigurację
        /// </summary>
        public static void Save()
        {
            //ustawienia użytkownika
            NetworkCredential credentials = null;
            //ustawienia proxy
            WebProxy proxy = null;
            //adres
            string proxyAddr = string.Empty;
            //port 
            int proxyPort = -1;
            //username
            string username = string.Empty;
            //password
            string password = string.Empty;
            //domyślne ustawienia użytkownika
            bool useDefaultCredentials = true;
            try
            {
                credentials = (NetworkCredential)Configuration.Proxy.Credentials;
                proxy = (WebProxy)Configuration.Proxy;

                //sprawdź poprawność danych Credentials
                if (credentials != null &&
                    !string.IsNullOrEmpty(credentials.UserName) &&
                    !string.IsNullOrEmpty(credentials.Password))
                {
                    username = credentials.UserName;
                    password = credentials.Password;
                }
                else
                    proxy.UseDefaultCredentials = true;

                //sprawdź poprawność danych Proxy
                if (proxy.Address != null &&
                    !string.IsNullOrEmpty(proxy.Address.Host) &&
                    proxy.Address.Port > -1)
                {
                    proxyAddr = proxy.Address.Host;
                    proxyPort = proxy.Address.Port;
                }

                useDefaultCredentials = proxy.UseDefaultCredentials;
            }
            catch (Exception e)
            {
                IApplication.Logger.Write(IApplication.LoggerEventType.Error, e.Message, "[Configuration.Save] Błąd podczas zapisywania proxy!");
            }

            XDocument conf = new XDocument(
                new XDeclaration("1.0", "utf-8", "yes"),
                new XElement("configuration",
                    new XComment("Parametry aplikacji:\n\ttopmost - okno zawsze na wierzchu\n\tshowInTaskbar - czy aplikacja ma byc widoczna na pasku zadan\n\tczy aplikacja ma byc widoczna w zasobniku systemowym"),
                    new XElement("application",
                        new XAttribute("topmost", Configuration.TopMost),
                        new XAttribute("showInTaskbar", Configuration.ShowInTaskbar),
                        new XAttribute("showInTray", Configuration.ShowInTray)),
                    new XComment("Parametry kanału wiadomości : address - adres url kanału"),
                    new XElement("channel",
                        new XAttribute("address", Configuration.ChannelAddress)),
                    new XComment("Parametry serwera proxy :\n\tusername - nazwa użytkownika\n\tpassword - hasło do serwera\n\taddress - adres serwera\n\tport - port serwera\n\tuseDefaultCredentials - czy używać domyślnych ustawień użytkownika"),
                    new XElement("proxy",
                        new XAttribute("username", username),
                        new XAttribute("password", password),
                        new XAttribute("address", proxyAddr),
                        new XAttribute("port", proxyPort),
                        new XAttribute("useDefaultCredentials", useDefaultCredentials)),
                    new XComment("Historia ostatnich wiadomości"),
                    new XElement("history",
                        from entry in Configuration.HistoryList
                        select new XElement("entry",
                            new XAttribute("isVisited", entry.IsVisited),
                            new XAttribute("title", entry.Details.Title),
                            new XAttribute("description", entry.Details.Description),
                            new XAttribute("link", entry.Details.Link),
                            new XAttribute("pubDate", entry.Details.PubDate)))));

            conf.Save(CONFIG_FILE);
        }

        /// <summary>
        /// Okno zawsze na wierzchu
        /// </summary>
        public static bool TopMost
        {
            get;
            set;
        }

        /// <summary>
        /// Pokazuje okno na pasku zadań lub nie
        /// </summary>
        public static bool ShowInTaskbar
        {
            get;
            set;
        }

        /// <summary>
        /// Pokazuje aplikację w zasobniku lub nie
        /// </summary>
        public static bool ShowInTray
        {
            get;
            set;
        }

        /// <summary>
        /// Adres kanału RSS
        /// </summary>
        public static string ChannelAddress
        {
            get;
            set;
        }

        /// <summary>
        /// Ustawienia serwera proxy
        /// </summary>
        public static IWebProxy Proxy
        {
            get;
            set;
        }

        /// <summary>
        /// Lista z historią ostatnich wiadomości
        /// </summary>
        public static IList<RssMessage> HistoryList
        {
            get;
            set;
        }

        /// <summary>
        /// plik konfiguracyjny
        /// </summary>
        private const string CONFIG_FILE = "configuration.xml";

        /// <summary>
        /// Strona domowa aplikacji
        /// </summary>
        public const string APP_HOMEPAGE = @"http://rssbar.codeplex.com/";
    }
}
